nv.array = new function () {
    var $this = this;
    $this.BREAK = {};
    $this.isEmpty = $this.IsEmpty = function (obj) {
        if (typeof obj === 'object') {
            for (var name in obj) {
                if (obj.hasOwnProperty(name)) {
                    return false;
                }
            }
            return true;
        }
        return false;
    };
    $this.count = $this.Count = function (obj) {
        var count = 0;
        for (var i in obj) {
            if (obj.hasOwnProperty(i)) {
                count++;
            }
        }
        return count;
    };
    $this.iterate = $this.Iterate = function (obj, callback, breakFlag) {
        var onlyVal = (callback.length < 2);
        for (var i in obj) {
            if (obj.hasOwnProperty(i)) {
                var returnVal = (onlyVal ? callback(obj[i]) : callback(i, obj[i]));
                if (returnVal === nv.array.BREAK) {
                    break;
                }
                if (breakFlag != null && (typeof breakFlag == 'function') && breakFlag() == true) break;
            }
        }
    };
    $this.flip = $this.Flip = function (arr) {
        var result = {};
        $this.Iterate(arr, function (k, v) {
            result[v] = k;
        });
        return result;
    };
    $this.combine = $this.Combine = function (keys, values) {
        var temp = [];
        var result = [];
        var i = 0;
        $this.Iterate(keys, function (k) {
            temp[i] = k;
            i++;
        });
        i = 0;
        $this.Iterate(values, function (v) {
            result[temp[i]] = v;
            i++;
        });
        return result;
    };
    if (!Object.keys) {
        $this.keys = $this.Keys = function (arr) {
            var keys = [];
            $this.Iterate(arr, function (k, v) {
                keys.push(k);
            });
            return keys;
        };
    } else {
        $this.keys = $this.Keys = Object.keys;
    }
    $this.keysToTrue = $this.KeysToTrue = function (arr) {
        var keys = {};
        $this.Iterate(arr, function (k, v) {
            keys[k] = true;;
        });
        return keys;
    };
    $this.values = $this.Values = function (obj) {
        var values = [];
        for (var k in obj) {
            if (obj.hasOwnProperty(k)) values.push(obj[k]);
        }
        return values;
    };
    $this.clone = $this.Clone = function (arr) {
        var copy = [];
        $this.Iterate(arr, function (k, v) {
            copy[k] = v;
        });
        return copy;
    };
    $this.keySort = function (inputArr, keyTransform, sorter) {
        if (typeof keyTransform == 'undefined') keyTransform = function (key) {
                return key;
            };
        if (typeof sorter == 'undefined') {
            sorter = function (a, b) {
                a = keyTransform(a);
                b = keyTransform(b);
                if (a > b) return 1;
                if (a < b) return -1;
                return 0;
            };
        }
        var keys = $this.keys(inputArr);
        keys = keys.sort();
        var sorted = {};
        $this.iterate(keys, function (key) {
            sorted[key] = inputArr[key];
        });
        return sorted;
    };
    $this.valueSort = $this.ValueSort = function (inputArr, sorter) {
        var valArr = [],
            keyArr = [],
            tempKeyVal, tempValue, ret, k = '',
            i = 0,
            populateArr = [];
        if (typeof sorter == 'undefined') {
            sorter = function (a, b) {
                if (a > b) {
                    return 1;
                }
                if (a < b) {
                    return -1;
                }
                return 0;
            };
        }
        var sorterNew = function (keyArr, valArr) {
            for (var i = valArr.length - 2; i >= 0; i--) {
                for (var j = 0; j <= i; j++) {
                    ret = sorter(valArr[j + 1], valArr[j]);
                    if (ret < 0) {
                        tempValue = valArr[j];
                        valArr[j] = valArr[j + 1];
                        valArr[j + 1] = tempValue;
                        tempKeyVal = keyArr[j];
                        keyArr[j] = keyArr[j + 1];
                        keyArr[j + 1] = tempKeyVal;
                    }
                }
            }
        };
        for (k in inputArr) {
            if (inputArr.hasOwnProperty(k)) {
                valArr.push(inputArr[k]);
                keyArr.push(k);
            }
        }
        try {
            sorterNew(keyArr, valArr);
        } catch (e) {
            return false;
        }
        for (i = 0; i < valArr.length; i++) {
            populateArr[keyArr[i]] = valArr[i];
        }
        return populateArr;
    };
    $this.sortBy = function (arr, key) {
        if (!key || !arr) {
            return arr;
        }
        return arr.slice().sort(function (a, b) {
            return a[key] - b[key];
        });
    };
    $this.merge = $this.Merge = function (destination, source) {
        nv.array.iterate(source, function (k, v) {
            if (parseInt(k).toString() == k) {
                destination.push(v);
            } else {
                destination[k] = v;
            }
        });
        return destination;
    };
    if (!Array.prototype.filter) {
        $this.filter = function (arr, fun) {
            "use strict";
            if (arr === void 0 || arr === null)
                throw new TypeError();
            var t = Object(arr);
            var len = t.length >>> 0;
            if (typeof fun !== "function")
                throw new TypeError();
            var res = [];
            var thisp = arguments[2];
            for (var i = 0; i < len; i++) {
                if (i in t) {
                    var val = t[i];
                    if (fun.call(thisp, val, i, t))
                        res.push(val);
                }
            }
            return res;
        };
    } else {
        $this.filter = function (arr, fun, thisp) {
            return arr.filter(fun, thisp);
        };
    }
    $this.isArray = Array.isArray || function (arr) {
        return Object.prototype.toString.call(arr) === "[object Array]";
    };
    $this.find = function (arr, fun, thisp) {
        if (!arr) return null;
        for (var i = 0; i < arr.length; i++) {
            var value = arr[i];
            if (fun.call(thisp, value, i, arr)) {
                return value;
            }
        }
        return null;
    };
    if (!Array.prototype.map) {
        $this.map = function (arr, fun) {
            "use strict";
            if (arr === void 0 || arr === null)
                throw new TypeError();
            var t = Object(arr);
            var len = t.length >>> 0;
            if (typeof fun !== "function")
                throw new TypeError();
            var res = new Array(len);
            var thisp = arguments[1];
            for (var i = 0; i < len; i++) {
                if (i in t)
                    res[i] = fun.call(thisp, t[i], i, t);
            }
            return res;
        };
    } else {
        $this.map = function (arr, fun, thisp) {
            return arr.map(fun, thisp);
        };
    }
    if (!Array.prototype.reduce) {
        $this.reduce = function (arr, fun) {
            "use strict";
            if (arr === void 0 || arr === null)
                throw new TypeError();
            var t = Object(arr);
            var len = t.length >>> 0;
            if (typeof fun !== "function")
                throw new TypeError();
            if (len == 0 && arguments.length == 2)
                throw new TypeError();
            var k = 0;
            var accumulator;
            if (arguments.length >= 3) {
                accumulator = arguments[2];
            } else {
                do {
                    if (k in t) {
                        accumulator = t[k++];
                        break;
                    }
                    if (++k >= len)
                        throw new TypeError();
                }
                while (true);
            }
            while (k < len) {
                if (k in t)
                    accumulator = fun.call(undefined, accumulator, t[k], k, t);
                k++;
            }
            return accumulator;
        };
    } else {
        $this.reduce = function (arr, fun, initialValue) {
            return arr.reduce(fun, initialValue);
        };
    }
    if (!Array.prototype.indexOf) {
        $this.indexOf = function (arr, searchElement) {
            "use strict";
            if (arr == null) {
                throw new TypeError();
            }
            var t = Object(arr);
            var len = t.length >>> 0;
            if (len === 0) {
                return -1;
            }
            var n = 0;
            if (arguments.length > 2) {
                n = Number(arguments[2]);
                if (n != n) {
                    n = 0;
                } else if (n != 0 && n != Infinity && n != -Infinity) {
                    n = (n > 0 || -1) * Math.floor(Math.abs(n));
                }
            }
            if (n >= len) {
                return -1;
            }
            var k = n >= 0 ? n : Math.max(len - Math.abs(n), 0);
            for (; k < len; k++) {
                if (k in t && t[k] === searchElement) {
                    return k;
                }
            }
            return -1;
        };
    } else {
        $this.indexOf = function (arr, searchElement) {
            return Array.prototype.indexOf.apply(arr, Array.prototype.slice.call(arguments, 1));
        };
    }
    if (!Array.prototype.forEach) {
        $this.forEach = function (arr, fun) {
            "use strict";
            if (arr === void 0 || arr === null)
                throw new TypeError();
            var t = Object(arr);
            var len = t.length >>> 0;
            if (typeof fun !== "function")
                throw new TypeError();
            var thisp = arguments[2];
            for (var i = 0; i < len; i++) {
                if (i in t)
                    fun.call(thisp, t[i], i, t);
            }
        };
    } else {
        $this.forEach = function (arr, fun, thisp) {
            return arr.forEach(fun, thisp);
        };
    }
    if (!Function.prototype.bind) {
        $this.bind = function bind(fun, context) {
            var args = Array.prototype.slice.call(arguments, 2);
            return function () {
                return fun.apply(context, args);
            };
        };
    } else {
        $this.bind = function (fun) {
            Function.prototype.bind.apply(func, Array.prototype.slice.call(arguments, 1));
        };
    }
    $this.removedups = function (arr, inFun) {
        var fun = inFun || function (o) {
                return o;
            };
        var lookup = {};
        return $this.filter(arr, function (o) {
            var key = fun(o);
            if (lookup[key] !== undefined)
                return false;
            lookup[key] = o;
            return true;
        });
    };
    $this.arraysEqual = function (l, r) {
        if (!l || !r) {
            return false;
        }
        if (l.length != r.length) {
            return false;
        }
        for (var i = 0; i < l.length; i++) {
            if (l[i] !== r[i]) {
                return false;
            }
        }
        return true;
    };
    $this.keyForValue = function (obj, value) {
        for (var k in obj) {
            var current = obj[k];
            if (current == value)
                return k;
        }
        return null;
    };
};